#include "SW_I2C.h"
#include "gpio.h"

// #include "delay.h"

#define I2C_PORT                 GPIOB
#define SDA_pin                  ADC_SDA_Pin
#define SCL_pin                  ADC_SCL_Pin
#define SW_I2C_OUT()             
#define SW_I2C_IN()              SDA_HIGH()
#define SDA_HIGH()               do{(I2C_PORT->BSRR = SDA_pin);}while(0)
#define SDA_LOW()                do{(I2C_PORT->BRR = SDA_pin);}while(0)
#define SCL_HIGH()               do{(I2C_PORT->BSRR = SCL_pin);}while(0)
#define SCL_LOW()                do{(I2C_PORT->BRR = SCL_pin);}while(0)
#define SDA_IN()                 (I2C_PORT->IDR & SDA_pin)
#define I2C_timeout              250
//////////////////////////////////////////////////////////
#define I2C_Delay 1

#define _delay_ms(ms) HAL_Delay(ms)


void _delay_us(uint32_t nus)
{
	uint32_t i;
	for(i=0; i<nus; i++)
    {
		__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();//8
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();//16
        __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();//24

	}
}

void SW_I2C_init(void)
{
    SW_I2C_OUT();
    _delay_ms(10);
    SDA_HIGH();
    SCL_HIGH();
}

void SW_I2C_start(void)
{
    SDA_HIGH();
    SCL_HIGH();
    _delay_us(I2C_Delay);
    SDA_LOW();
    _delay_us(I2C_Delay);
    SCL_LOW();
    _delay_us(I2C_Delay);
}

void SW_I2C_stop(void)
{
    SDA_LOW();
    _delay_us(I2C_Delay);
    SCL_HIGH();
    _delay_us(I2C_Delay);
    SDA_HIGH();
}

void SW_I2C_write(uint8_t value)
{
    unsigned char i = 0x08;
    while (i > 0x00)
    {
        if (((value & 0x80) >> 0x07) != 0x00)
        {
            SDA_HIGH();
        }
        else
        {
            SDA_LOW();
        }
        value <<= 1;
        _delay_us(I2C_Delay);
        SCL_HIGH();
        _delay_us(I2C_Delay);
        SCL_LOW();
        i--;
    };
}

uint8_t SW_I2C_wait_ACK(void)
{
    uint8_t timeout = 0;
    unsigned char resp = 1;

    SW_I2C_IN();
    _delay_us(I2C_Delay);
    SCL_HIGH();
    while (SDA_IN() != 0x00)
    {
        timeout++;
        if (timeout > I2C_timeout)
        {
            resp = 0;
            SW_I2C_OUT();
            break;
        }
    };

    if (resp == 0)
    {
        // no resp, stop this
        SCL_LOW();
        _delay_us(I2C_Delay);
        SW_I2C_OUT();
        SW_I2C_stop();
    }
    else
    {
        _delay_us(I2C_Delay);
        SCL_LOW();
        SW_I2C_OUT();
    }
    return resp;
}

// ack: 1: send ack 2: nack
uint8_t SW_I2C_read(uint8_t ack)
{
    unsigned char i = 0x08;
    unsigned char j = 0x00;
    SW_I2C_IN();
    while (i > 0x00)
    {
        SCL_LOW();
        _delay_us(I2C_Delay);
        SCL_HIGH();
        _delay_us(I2C_Delay);
        j <<= 1;
        if (SDA_IN() != 0x00)
        {
            j++;
        }
        //_delay_us(I2C_Delay);
        i--;
    };

    // ack
    SCL_LOW();
    SW_I2C_OUT();
    if (ack == 1)
    {
        SDA_LOW();
    }
    else
    {
        SDA_HIGH();
    }
    _delay_us(I2C_Delay);
    SCL_HIGH();
    _delay_us(I2C_Delay);
    SCL_LOW();
    //_delay_us(I2C_Delay);

    return j;
}
